﻿using System.Collections.Generic;
using Godot.core.os;

namespace Godot.core
{
    public partial class PathRemap : Object
    {
        private class __RemapData
        {
            public string always;
            public Dictionary<string, string> locale;

            public __RemapData()
            {
                locale = new Dictionary<string, string>();
            }
        }

        public static PathRemap singleton
        {
            get { return __singleton; }
        }

        protected static new void _bind_methods()
        {
        }

        public void add_remap(string p_from, string p_to, string p_locale = "") 
        {
	        if (!__remap.ContainsKey(p_from)) 
            {
		        __remap[p_from] = new __RemapData();
	        }

	        if (p_locale == "")
		        __remap[p_from].always = p_to;
	        else
		        __remap[p_from].locale[p_locale] = p_to;
        }

        public void load_remaps()
        {
            // default remaps first
	        List<string> remaps = Globals.singleton.get("remap/all");
            if(remaps != null)
	        {
		        int rlen = remaps.Count;

		        if( rlen % 2 != 0) return;

		        //List<string>::Read r = remaps.read();
		        for(int i = 0; i < rlen / 2; i++) 
                {
			        string from = remaps[i * 2 + 0];
			        string to = remaps[i * 2 + 1];
			        add_remap(from, to);
		        }
	        }


	        // platform remaps second, so override
	        remaps = Globals.singleton.get("remap/" + OS.singleton.get_name());
            if(remaps != null)
	        {
		        int rlen = remaps.Count;

		        if( rlen % 2 != 0) return;

		        for(int i = 0; i < rlen / 2; i++) 
                {
			        string from = remaps[i*2+0];
			        string to = remaps[i*2+1];
			        add_remap(from,to);
		        }
	        }


	        //locale based remaps
	        if (Globals.singleton.has("locale/translation_remaps")) 
            {
		        Dictionary<Variant, Variant> dremaps = Globals.singleton.get("locale/translation_remaps");

                foreach(Variant E in dremaps.Keys) 
                {
			        string source = E;
			        List<string> sa = dremaps[E];
			        int sas = sa.Count;

			        for(int i = 0; i < sas; i++) 
                    {
				        string s = sa[i];
				        int qp = s.LastIndexOf(":");
				        if (qp != -1) 
                        {
					        string path = s.Substring(0, qp);
					        string locale = s.Substring(qp + 1, s.Length);
					        add_remap(source, path, locale);
				        }
			        }
		        }

	        }
        }

        public PathRemap()
        {
            if (__singleton != null) return;
            __remap = new Dictionary<string, __RemapData>();
            __singleton = this;
        }

        private Dictionary<string, __RemapData> __remap;
        private static PathRemap __singleton;

        internal string get_remap(string local_path)
        {
            throw new System.NotImplementedException();
        }
    }

    public partial class PathRemap
    {
        #region OBJ_TYPE( PathRemap, Object )
        /* TYPE API */
        public override string get_type() { return "PathRemap"; }

        public override string get_save_type() { return get_type(); } //type stored when saving

        public override StringName get_type_name() { return (StringName)get_type_static(); }

        public override bool is_type(string p_type) { return (p_type == "PathRemap") ? true : base.is_type(p_type); }

        protected override void _initialize_typev() { initialize_type(); }

        protected override bool _setv(StringName p_name, Variant p_property)
        {
            if (base._setv(p_name, p_property))
                return true;

            if (typeof(PathRemap).GetMethod("_set") != typeof(Object).GetMethod("_set"))
            {
                return _set(p_name, p_property);
            }
            return false;
        }

        protected override bool _getv(StringName p_name, ref Variant r_property)
        {
            if (typeof(PathRemap).GetMethod("_get") != typeof(Object).GetMethod("_get"))
            {
                if (_get(p_name, ref r_property))
                    return true;
            }

            return base._getv(p_name, ref r_property);
        }

        protected override void _get_property_listv(ref List<PropertyInfo> p_list, bool p_reversed)
        {
            if (!p_reversed)
            {
                base._get_property_listv(ref p_list, p_reversed);
            }

            p_list.Add(new PropertyInfo(Variant.Type.NIL, get_type_static(), PropertyHint.PROPERTY_HINT_NONE, "", (int)PropertyUsageFlags.PROPERTY_USAGE_CATEGORY));

            if (!_is_gpl_reversed())
                ObjectTypeDB.get_property_list("PathRemap", ref p_list, true);

            if (typeof(PathRemap).GetMethod("_get_property_list") != typeof(Object).GetMethod("_get_property_list"))
            {
                _get_property_list(ref p_list);
            }

            if (_is_gpl_reversed())
                ObjectTypeDB.get_property_list("PathRemap", ref p_list, true);

            if (p_reversed)
            {
                base._get_property_listv(ref p_list, p_reversed);
            }
        }

        protected override void _notificationv(int p_notification, bool p_reversed)
        {
            if (!p_reversed)
                base._notificationv(p_notification, p_reversed);

            if (typeof(PathRemap).GetMethod("_notification") != typeof(Object).GetMethod("_notification"))
            {
                _notification(p_notification);
            }

            if (p_reversed)
                base._notificationv(p_notification, p_reversed);
        }

        public static new string get_type_static() { return "PathRemap"; }

        public static new string get_parent_type_static() { return Object.get_type_static(); }

        public static new void get_inheritance_list_static(ref List<string> r_inheritance_list)
        {
            Object.get_inheritance_list_static(ref r_inheritance_list);
            r_inheritance_list.Add(get_type_static());
        }

        public static new string get_category_static()
        {
            string category = Object.get_category_static();
            if (typeof(PathRemap).GetMethod("_get_category") != typeof(Object).GetMethod("_get_category"))
            {
                if (category != "")
                    category += "/";
                category += _get_category();
            }
            return category;
        }

        public static new string inherits_static() { return "Object"; }

        public static new void get_valid_parents_static(ref List<string> p_parents)
        {
            if (typeof(PathRemap).GetMethod("_get_valid_parents_static") != typeof(Object).GetMethod("_get_valid_parents_static"))
            {
                PathRemap._get_valid_parents_static(ref p_parents);
            }

            Object.get_valid_parents_static(ref p_parents);
        }

        public static new void initialize_type()
        {
            if (__initialized)
                return;
            Object.initialize_type();
            ObjectTypeDB._add_type<PathRemap>();
            if (typeof(PathRemap).GetMethod("_bind_methods") != typeof(Object).GetMethod("_bind_methods"))
                _bind_methods();
            __initialized = true;
        }

        private static bool __initialized = false;
        #endregion
    }
}
